<?php
/**
 * Utility class for dealing with resources i.e. compression of resources on production sites
 * 
 * @package Mhtml
 * @author Matt Pike  
 */   
class Resource{

	protected $compressResources 	= null;
	protected $compressionHandlers = array();
	
	/**
	 * @var JsCompression
	 */
	private $scriptCompressionHandler = null;
	
	/**
	 * Initialize a resource a handler
	 *
	 * @param boolean $compressScripts
	 * @param boolean $compressStylesheets
	 */
	public function __construct($returnCompressedResources){
		$this->setCompressResources($returnCompressedResources);

	}
	
	/**
	 * Set whether to return resources compressed or not
	 *
	 * @param boolean $compressResources
	 */
	public function setCompressResources($returnCompressedResources){
		$this->compressResources = $returnCompressedResources;
	}
	
	/**
	 * Add a handler for supporting resource compression
	 *
	 * @param Compression $compressionHandler
	 */
	public function addCompressionHandler(Compression $compressionHandler){
		$this->compressionHandlers[] = $compressionHandler;
	}

	/**
	 * Add handlers for supporting resource compression
	 *
	 * @param array $compressionHandlers
	 */
	public function addCompressionHandlers(array $compressionHandlers){
		foreach($compressionHandlers as $handler){
			$this->addCompressionHandler($handler);
		}
	}
	
	/**
	 * Alias for getWebPath()
	 *
	 * @param string $filename
	 */
	public function get($filename){
		return $this->getWebPath($filename);
	}
	
	/**
	 * If $this->compressResources, return web path to compressed resource 
	 * Otherwise return web path to uncompressed resource
	 *
	 * @param string
	 * @return string
	 */
	public function getWebPath($filename){
		$handler = $this->getHandler($filename);
		if($this->compressResources){
			if(!$this->isFileCompressed($handler,$filename)){
				$handler->compress($filename);
			}
			return $handler->getDomain().$handler->getPathCompressed($filename); 
		}else{
			return $handler->getDomain().$handler->getPathUncompressed($filename); 
		}
	}
	
	/**
	 * If $this->compressResources, return absolute path to compressed resource 
	 * Otherwise return absolute path to uncompressed resource
	 *
	 * @param string
	 * @return string
	 */
	public function getAbsolutePath($filename){
		$handler = $this->getHandler($filename);
		if($this->compressResources){
			if(!$this->isFileCompressed($handler,$filename)){
				$handler->compress($filename);
			}
			return $handler->getWebRootAbsPath().$handler->getPathCompressed($filename); 
		}else{
			return $handler->getWebRootAbsPath().$handler->getPathUncompressed($filename); 
		}
	}
	
	/**
	 * If $this->compressResources, return html to include compressed resource 
	 * Otherwise return html to include uncompressed resource
	 *
	 * @param string
	 * @return MhtmlElement
	 */
	public function getHtml($filename){
		$extension = $this->getExtension($filename);
		require_once("MhtmlElement.php");
		switch($extension){
			case "js":	return new MhtmlElement("script",array("type"=>"text/javascript","src"=>$this->getWebPath($filename)));
			case "css":	return new MhtmlElement("link",array("rel"=>"stylesheet","href"=>$this->getWebPath($filename),"type"=>"text/css"));
			default: throw new Exception("Unable to convert $filename to HTML");
		}
	}
	
	/**
	 * Clear and rebuild cache
	 */
	public function rebuildCache(){
		$this->clearCache();
		$this->buildCache();
	}
	
	/**
	 * Delete all cached/compressed resources
	 *
	 * @return boolean
	 */
	public function clearCache(){
		foreach($this->getCompressionHandlers() as $handler){
			$absPath = $handler->getWebRootAbsPath().$handler->getCompressedDirectory();
			$files = new DirectoryIterator($absPath);
			foreach($files as $file){
				$filename = $file->getFilename();
				if($file->isFile() && in_array($this->getExtension($filename),$handler->getSupportedFileTypes())){
					if(!unlink($absPath."/".$filename)){
						return false;
					}
				}
			}
		}
		return true;
	}
	
	/**
	 * Build cached/compressed resources
	 *
	 * @return boolean
	 */
	public function buildCache(){
		foreach($this->getCompressionHandlers() as $handler){
			$absPath = $handler->getWebRootAbsPath().$handler->getUncompressedDirectory();
			$files = new DirectoryIterator($absPath);
			foreach($files as $file){
				$filename = $file->getFilename();
				if($file->isFile() && in_array($this->getExtension($filename),$handler->getSupportedFileTypes())){
					$handler->compress($filename);
				}
			}
		}
		return true;
	}
	
	/**
	 * Check if the compressed file is present, compress and save if isnt
	 *
	 * @param Compression $handler
	 * @param string $filename
	 */
	protected function isFileCompressed(Compression $handler,$filename){
		if(file_exists($handler->getWebRootAbsPath().$handler->getCompressedDirectory().$filename)){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * Get handler for a specific filetype
	 *
	 * @param string $filename
	 * @return Compression
	 */
	protected function getHandler($filename){
		$extension = $this->getExtension($filename);
		foreach($this->getCompressionHandlers() as $handler){
			if(in_array($extension,$handler->getSupportedFileTypes())){
				return $handler;
			}
		}
		throw new Exception("Unable to find relevant handler for ".$filename);
	}
	
	/**
	 * Return compression handlers
	 *
	 * @return array
	 */
	public function getCompressionHandlers(){
		return $this->compressionHandlers;
	}
	
	protected function getExtension($filename){
		$file = explode(".",$filename);
		return end($file);
	}
}